home *** CD-ROM | disk | FTP | other *** search
- /* Primitives for word-abbrev mode.
- Copyright (C) 1985, 1986, 1992, 1993 Free Software Foundation, Inc.
-
- This file is part of XEmacs.
-
- XEmacs is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published by the
- Free Software Foundation; either version 2, or (at your option) any
- later version.
-
- XEmacs is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- for more details.
-
- You should have received a copy of the GNU General Public License
- along with XEmacs; see the file COPYING. If not, write to the Free
- Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
-
- /* Synched up with: FSF 19.28. Note that there are many more functions in
- FSF's abbrev.c. These have been moved into Lisp in XEmacs. */
-
- /* This file has been Mule-ized. */
-
- #include <config.h>
- #include "lisp.h"
-
- #include "commands.h"
- #include "buffer.h"
- #include "window.h"
- #include "insdel.h"
-
- /* An abbrev table is an obarray.
- Each defined abbrev is represented by a symbol in that obarray
- whose print name is the abbreviation.
- The symbol's value is a string which is the expansion.
- If its function definition is non-nil, it is called
- after the expansion is done.
- The plist slot of the abbrev symbol is its usage count. */
-
- /* The table of global abbrevs. These are in effect
- in any buffer in which abbrev mode is turned on. */
- Lisp_Object Vglobal_abbrev_table;
-
- int abbrev_all_caps;
-
- /* Non-nil => use this location as the start of abbrev to expand
- (rather than taking the word before point as the abbrev) */
- Lisp_Object Vabbrev_start_location;
-
- /* Buffer that Vabbrev_start_location applies to */
- Lisp_Object Vabbrev_start_location_buffer;
-
- /* The symbol representing the abbrev most recently expanded */
- Lisp_Object Vlast_abbrev;
-
- /* A string for the actual text of the abbrev most recently expanded.
- This has more info than Vlast_abbrev since case is significant. */
- Lisp_Object Vlast_abbrev_text;
-
- /* Character address of start of last abbrev expanded */
- int last_abbrev_point;
-
- /* Hook to run before expanding any abbrev. */
- Lisp_Object Vpre_abbrev_expand_hook, Qpre_abbrev_expand_hook;
-
-
- /* Expand the word before point, if it is an abbrev.
- Returns Qt if an expansion is done. */
-
- DEFUN ("expand-abbrev", Fexpand_abbrev, Sexpand_abbrev, 0, 0, "",
- "Expand the abbrev before point, if there is an abbrev there.\n\
- Effective when explicitly called even when `abbrev-mode' is nil.\n\
- Returns t if expansion took place.")
- ()
- {
- /* This function can GC */
- REGISTER Bufbyte *buffer, *p;
- REGISTER Bufpos wordstart, wordend, idx;
- Charcount whitecnt;
- Charcount uccount = 0, lccount = 0;
- REGISTER Lisp_Object sym;
- Lisp_Object expansion, hook, value;
- struct buffer *buf = current_buffer;
- Lisp_Object lbuf;
- int oldmodiff = BUF_MODIFF (buf);
-
- XSETBUFFER (lbuf, buf);
- if (!NILP (Vrun_hooks))
- call1 (Vrun_hooks, Qpre_abbrev_expand_hook);
- /* If the hook changes the buffer, treat that as having "done an
- expansion". */
- value = (BUF_MODIFF (buf) != oldmodiff ? Qt : Qnil);
-
- if (!BUFFERP (Vabbrev_start_location_buffer) ||
- XBUFFER (Vabbrev_start_location_buffer) != buf)
- Vabbrev_start_location = Qnil;
- if (!NILP (Vabbrev_start_location))
- {
- wordstart = get_bufpos (buf, Vabbrev_start_location, GB_COERCE_RANGE);
- Vabbrev_start_location = Qnil;
- if (BUF_FETCH_CHAR (buf, wordstart) == '-')
- buffer_delete_range (buf, wordstart, wordstart + 1, 0);
- }
- else
- wordstart = scan_words (buf, BUF_PT (buf), -1);
-
- if (!wordstart)
- return value;
-
- wordend = scan_words (buf, wordstart, 1);
- if (!wordend)
- return value;
-
- if (wordend > BUF_PT (buf))
- wordend = BUF_PT (buf);
- whitecnt = BUF_PT (buf) - wordend;
- if (wordend <= wordstart)
- return value;
-
- p = buffer = (Bufbyte *) alloca (MAX_EMCHAR_LEN*(wordend - wordstart));
-
- for (idx = wordstart; idx < wordend; idx++)
- {
- REGISTER Emchar c = BUF_FETCH_CHAR (buf, idx);
- if (UPPERCASEP (buf, c))
- c = DOWNCASE (buf, c), uccount++;
- else if (! NOCASEP (buf, c))
- lccount++;
- p += emchar_to_charptr (c, p);
- }
-
- if (VECTORP (buf->abbrev_table))
- sym = oblookup (buf->abbrev_table,
- buffer,
- p - buffer);
- else
- sym = Qzero;
- if (INTP (sym) || NILP (XSYMBOL (sym)->value))
- sym = oblookup (Vglobal_abbrev_table,
- buffer,
- p - buffer);
- if (INTP (sym) || NILP (XSYMBOL (sym)->value))
- return value;
-
- if (INTERACTIVE && !EQ (minibuf_window, Fselected_window (Qnil)))
- {
- BUF_SET_PT (buf, wordend);
- Fundo_boundary ();
- }
- BUF_SET_PT (buf, wordstart);
- Vlast_abbrev_text =
- make_string_from_buffer (buf, wordstart, wordend - wordstart);
- buffer_delete_range (buf, wordstart, wordend, 0);
-
- /* Now sym is the abbrev symbol. */
- Vlast_abbrev = sym;
- last_abbrev_point = wordstart;
-
- if (INTP (XSYMBOL (sym)->plist))
- XSETINT (XSYMBOL (sym)->plist,
- XINT (XSYMBOL (sym)->plist) + 1); /* Increment use count */
-
- expansion = XSYMBOL (sym)->value;
- buffer_insert_lisp_string (buf, expansion);
- BUF_SET_PT (buf, BUF_PT (buf) + whitecnt);
-
- if (uccount && !lccount)
- {
- /* Abbrev was all caps */
- /* If expansion is multiple words, normally capitalize each word */
- /* This used to be if (!... && ... >= ...) Fcapitalize; else Fupcase
- but Megatest 68000 compiler can't handle that */
- if (!abbrev_all_caps)
- if (scan_words (buf, BUF_PT (buf), -1) >
- scan_words (buf, wordstart, 1))
- {
- upcase_initials_region (buf, make_number (wordstart),
- make_number (BUF_PT (buf)));
- goto caped;
- }
- /* If expansion is one word, or if user says so, upcase it all. */
- Fupcase_region (make_number (wordstart), make_number (BUF_PT (buf)),
- lbuf);
- caped: ;
- }
- else if (uccount)
- {
- /* Abbrev included some caps. Cap first initial of expansion */
- int speccount = specpdl_depth ();
- Bufpos old_pt = BUF_PT (buf);
-
- /* Don't let Fcapitalize_word operate on text after point. */
- record_unwind_protect (save_restriction_restore,
- save_restriction_save ());
- Fnarrow_to_region (make_number (BUF_BEGV (buf)),
- make_number (BUF_PT (buf)), lbuf);
-
- BUF_SET_PT (buf, wordstart);
- Fcapitalize_word (make_number (1), lbuf);
- BUF_SET_PT (buf, old_pt);
-
- unbind_to (speccount, Qnil);
- }
-
- hook = XSYMBOL (sym)->function;
- if (!NILP (hook) && !EQ (hook, Qunbound))
- call0 (hook);
-
- return Qt;
- }
-
- void
- syms_of_abbrev (void)
- {
- defsymbol (&Qpre_abbrev_expand_hook, "pre-abbrev-expand-hook");
- defsubr (&Sexpand_abbrev);
- }
-
- void
- vars_of_abbrev (void)
- {
- DEFVAR_LISP ("global-abbrev-table", &Vglobal_abbrev_table,
- "The abbrev table whose abbrevs affect all buffers.\n\
- Each buffer may also have a local abbrev table.\n\
- If it does, the local table overrides the global one\n\
- for any particular abbrev defined in both.");
- Vglobal_abbrev_table = Qnil; /* setup by Lisp code */
-
- DEFVAR_LISP ("last-abbrev", &Vlast_abbrev,
- "The abbrev-symbol of the last abbrev expanded.\n\
- See the function `abbrev-symbol'.");
-
- DEFVAR_LISP ("last-abbrev-text", &Vlast_abbrev_text,
- "The exact text of the last abbrev expanded.\n\
- nil if the abbrev has already been unexpanded.");
-
- DEFVAR_INT ("last-abbrev-location", &last_abbrev_point,
- "The location of the start of the last abbrev expanded.");
-
- Vlast_abbrev = Qnil;
- Vlast_abbrev_text = Qnil;
- last_abbrev_point = 0;
-
- DEFVAR_LISP ("abbrev-start-location", &Vabbrev_start_location,
- "Buffer position for `expand-abbrev' to use as the start of the abbrev.\n\
- nil means use the word before point as the abbrev.\n\
- Calling `expand-abbrev' sets this to nil.");
- Vabbrev_start_location = Qnil;
-
- DEFVAR_LISP ("abbrev-start-location-buffer", &Vabbrev_start_location_buffer,
- "Buffer that `abbrev-start-location' has been set for.\n\
- Trying to expand an abbrev in any other buffer clears `abbrev-start-location'.");
- Vabbrev_start_location_buffer = Qnil;
-
- DEFVAR_BOOL ("abbrev-all-caps", &abbrev_all_caps,
- "*Set non-nil means expand multi-word abbrevs all caps if abbrev was so.");
- abbrev_all_caps = 0;
-
- DEFVAR_LISP ("pre-abbrev-expand-hook", &Vpre_abbrev_expand_hook,
- "Function or functions to be called before abbrev expansion is done.\n\
- This is the first thing that `expand-abbrev' does, and so this may change\n\
- the current abbrev table before abbrev lookup happens.");
- Vpre_abbrev_expand_hook = Qnil;
- }
-